package com.kayak.easysp.appsecurity;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kayak.dbutil.sql.SqlException;
import com.kayak.easysp.transbase.TransBean;
import com.kayak.exception.ErrorException;
import com.kayak.kkutils.CalendarUtil;
import com.kayak.kkutils.ErrorCode;
import com.kayak.kkutils.JsonUtil;
import com.kayak.kkutils.strutil.StringUtil;
import com.kayak.kkweb.sys.Global;
import com.kayak.kkweb.sys.SysBeans;

/**
 * 交易父类
 * 20160323
 * 执行步骤说明：
 *	--->doService() 供Action调用入口
 *  --->doMain()    流程处理主函数
 *  
 *  --->securityCheck 加密校验
 *  --->initParamSuper[initParam()]  初始化公共参数，并调用子类中添加参数initParam
 *  --->dataCheckSuper[dataCheck()]  数据校验：非空及格式
 *  --->busiCheckSuper[busiCheck()]  业务数据校验
 *  --->doBusi						 业务处理
 *  --->securityOut                  组包加密
 * */
public abstract class SecurityBase {

	private static final Logger log = LoggerFactory.getLogger(SecurityBase.class);
	
	private Logger logUtil = LoggerFactory.getLogger(this.getClass());


	/**
	 * 入口方法 根据transCode获取交易实例并执行
	 * add by guancj 20160304 
	 * Action调用的方法入口
	 * 
	 * @param transCode
	 *            交易码
	 * @param params
	 *            参数
	 * @param response
	 *            返回
	 */
	public static void doService(String transCode, Map<String, Object> params, HttpServletResponse response) {
		TransBean transBean = new TransBean();
		if (params == null || params.size() == 0 || StringUtil.isEmpty(transCode)) {
			transBean.addLocalParam(ErrorCode.RET_MSG, "服务已启动！");
			transBean.addLocalParam(ErrorCode.RET_CODE, "ok");
			returnClient((ServletResponse) response, transBean);
			return;
		}

		transBean.setRequest((Map<String, Object>) params);
		transBean.getLocalMap().putAll(params);

		try {
			if (StringUtils.isBlank(transCode)) {
				throw new ErrorException(ErrorCode.ERROR_9997_CODE, ErrorCode.ERROR_9997_MSG);
			}
			transBean.addLocalParam("trans_code", transCode);
			
			// 根据交易码生成实例
			SecurityBase comnService = (SecurityBase) SysBeans.getBean("s" + transCode);
			if (comnService == null) {
				throw new ErrorException("系统异常");
			}

			comnService.doMain(transBean);
			if(null==transBean.getLocalParam(ErrorCode.RET_CODE)
					||transBean.getLocalParam(ErrorCode.RET_CODE).equals("")){
				transBean.addLocalParam(ErrorCode.RET_CODE, "0000");
				transBean.addLocalParam(ErrorCode.RET_MSG, "交易成功");
			}
		} catch (ErrorException e) {
			log.error(e.getMessage(), e);
			if (e.getErroCode() == null) {
				// 通用返回错误
				transBean.addLocalParam(ErrorCode.RET_CODE, ErrorCode.ERROR_9999_CODE);
				transBean.addLocalParam(ErrorCode.RET_MSG, ErrorCode.ERROR_9999_MSG);
			} else {
				transBean.addLocalParam(ErrorCode.RET_CODE, e.getErroCode());
				transBean.addLocalParam(ErrorCode.RET_MSG, e.getMessage());
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			transBean.addLocalParam(ErrorCode.RET_CODE,ErrorCode.ERROR_9999_CODE);
			transBean.addLocalParam(ErrorCode.RET_MSG, ErrorCode.ERROR_9999_MSG);
		} finally {
			returnClient((ServletResponse) response, transBean);
		}
	}
	
	/**
	 * 执行请求
	 * 
	 * @param transBean
	 * @throws Exception
	 */
	public final void doMain(TransBean transBean) throws Exception {
		
		
	
		this.initParamSuper(transBean);
		
		this.dataCheckSuper(transBean);
		
		this.doBusi(transBean);	

	}
	
	/**
	 * 公共初始化参数
	 * 
	 * @param transBean
	 * @throws ErrorException
	 */
	private void initParamSuper(TransBean transBean) throws ErrorException {
		
		transBean.addLocalParam("trans_date", CalendarUtil.getDate());
		transBean.addLocalParam("trans_time", CalendarUtil.getTime());
		
		initParam(transBean);
	}

	public abstract void initParam(TransBean transBean) throws ErrorException;

	/**
	 * 公共验证参数不为空
	 * 
	 * @param transBean
	 * @throws ErrorException
	 */
	private void dataCheckSuper(TransBean transBean) throws ErrorException {
		
		dataCheck(transBean);
	}

	/**
	 * 验证参数不为空
	 * @param transBean
	 * @throws ErrorException
	 */
	public abstract void dataCheck(TransBean transBean) throws ErrorException;

	/**
	 * 公共业务逻辑校验
	 * 
	 * @param transBean
	 * @throws ErrorException
	 */
	public abstract void doBusi(TransBean transBean) throws ErrorException, SqlException, Exception;

	/**
	 * 
	 * @param httpResponse
	 * @param transBean
	 */
	private static void returnClient(ServletResponse httpResponse, TransBean transBean) {
		
		transBean.addResponse(ErrorCode.RET_CODE, transBean.getLocalParam(ErrorCode.RET_CODE));
		transBean.addResponse(ErrorCode.RET_MSG, transBean.getLocalParam(ErrorCode.RET_MSG));
		String retData = JsonUtil.objectToJson(transBean.getResponse());
		log.info("retrunClient:[{}]", retData);
		
		OutputStream out = null;
		try {
			out = httpResponse.getOutputStream();
			out.write(retData.getBytes(Global.charset()));
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e1) {
			}
		}
	}
	protected void logdebug(String msg){
		logUtil.debug(msg);
	}
	
	protected void logtrace(String msg){
		logUtil.trace(msg);
	}
	
	protected void loginfo(String msg){
		logUtil.info(msg);
	}
	
	protected void logwarn(String msg){
		logUtil.warn(msg);
	}
	
	protected void logerr(String msg){
		logUtil.error(msg);
	}
	
}
